package com.ruoyi.common.utils.pay;

import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.collect.Maps;
import com.ruoyi.common.constant.ApiConstants;
import com.ruoyi.common.utils.OrderUtil;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;


/**
 * @author ywh
 * @date 2021/5/24
 * @desc
 */
@Service
public class WXPayUtils {

    @Autowired
    private  WxPayService wxPayService;

    public  Map toAppPay(BigDecimal orderPrice, String payNo, Long orderId) {
        try {
            WxPayUnifiedOrderRequest wxPayRequest = new WxPayUnifiedOrderRequest();
            wxPayRequest.setBody("课程购买");
            wxPayRequest.setOutTradeNo(payNo);
            wxPayRequest.setTotalFee(orderPrice.multiply(new BigDecimal(100)).intValue());//元转成分
            wxPayRequest.setAttach(String.valueOf(orderId));
            wxPayRequest.setSpbillCreateIp(ApiConstants.SPBILL_CREATE_IP);
            wxPayRequest.setNotifyUrl(ApiConstants.WX_NOTIFY_URL);
            wxPayRequest.setTradeType("APP");
            WxPayUnifiedOrderResult orderResult = wxPayService.unifiedOrder(wxPayRequest);
            Map<String, String> resultMap = new TreeMap<>();//装载返回给页面的参数
            if (orderResult.getReturnCode().equalsIgnoreCase("FAIL")) {
                //接口调用失败
                System.out.println("调用预支付接口调用失败");
                return toFailMsg("调接口失败," + orderResult.getReturnMsg());
            } else if (orderResult.getReturnCode().equalsIgnoreCase("SUCCESS")) {
                System.out.println("调用预支付接口调用成功");
                String result_code = orderResult.getResultCode();//返回结果标识
                if (result_code.equalsIgnoreCase("FAIL")) {
                    System.out.println("获取预支付id出错");
                    return toFailMsg("获取预支付id失败");
                } else if (result_code.equalsIgnoreCase("SUCCESS")) {
                    System.out.println("获取预支付id成功");
                    //app支付需要返回参数
                    resultMap.put("prepayid", orderResult.getPrepayId());  //统一下单成成之后返回的prepay_id
                    resultMap.put("appid", orderResult.getAppid()); // 先生成paySign参数map
                    resultMap.put("partnerid", ApiConstants.MCH_ID); // 商户号
                    resultMap.put("package", "Sign=WXPay");  //APP使用
                    resultMap.put("noncestr", WXPayUtil.generateNonceStr()); //获取随机字符串
                    resultMap.put("timestamp", String.valueOf(System.currentTimeMillis()).substring(0, 10));  //时间戳
                    String sign = WXPayUtil.generateSignature(resultMap, ApiConstants.PAYKEY, WXPayConstants.SignType.MD5);
                    resultMap.put("paySign", sign); //此处根据返回的结果，和预支付id在此生成支付签证
                    return toSuccessResult(resultMap, "预支付id获取成功");
                } else {
                    System.out.println("获取预支付id出错");
                    return toFailMsg("获取预支付id失败,");
                }
            } else {
                System.out.println("调用预支付接口出现无法识别的错误");
                return toFailMsg("调接口失败," + orderResult.getReturnMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return toFailMsg("系统错误");
        }
    }


    /**
     * @return
     * @throws Exception
     */
    /*请求微信接口的封装*/
    public static Map toPickWeChat(BigDecimal pickMoney, String openId) throws Exception {
        /**1.拼凑企业支付需要的参数**/
        //提现金额(单位:元)
        //元转换为分,微信支付已分为单位
        Map<String, String> paraMap = Maps.newHashMap();
        //乘以100，转换为分
        BigDecimal transAmt = pickMoney.multiply(new BigDecimal(100));

        //微信公众号的appid
        paraMap.put("mch_appid", ApiConstants.APPLICATION_ID);
        //商户号
        paraMap.put("mchid", ApiConstants.MCH_ID);
        //openid("c从数据库中查询")
        paraMap.put("openid", openId);
        //金额
        paraMap.put("amount", String.valueOf(transAmt));
        //订单号
        paraMap.put("partner_trade_no", OrderUtil.getGoodsOrderNo());
        //随机字符串
        paraMap.put("nonce_str", OtherUtils.getNonceStr());

        ////企业付款操作说明信息
        paraMap.put("desc", "余额提现");

        paraMap.put("check_name", "NO_CHECK");

        //ip地址，地址可以不是真实地址
        paraMap.put("spbill_create_ip", ApiConstants.SPBILL_CREATE_IP);
        String returnInfo = WeChatWithdrawUtils.withdrawRequestOnce(paraMap, 3000, 3000, true);
        return OtherUtils.readStringXmlOut(returnInfo);
    }


    /**
     * 操作失败返回理由
     */
    public static Map<String, Object> toFailMsg(String msg) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", 1);
        map.put("msg", msg);
        return map;
    }

    /**
     * 操作成功携带数据返回
     */
    public static Map<String, Object> toSuccessResult(Object object, String msg) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", 0);
        map.put("msg", msg);
        map.put("data", object);
        return map;
    }

}
